import React from 'react';
import { injectAsyncReducer } from '@/utils/store/configStore';

const noop = () => null;

/**
 * 预加载组件（小程序可能会失效，但不影响）
 * @param {组件}} 组件
 * @param {redux} reducer
 */
function perLoad(component, reducer) {
	const state: any = {
		Component: null
	}; //返回state
	const reducerKeys = Object.keys(reducer);
	const storeReducer = {};
	let promiseList = reducerKeys.map(key => {
		return reducer[key]().then(res => {
			storeReducer[key] = res.default;
			return res;
		});
	});
	promiseList = [component(), ...promiseList];
	state.promise = Promise.all(promiseList)
		.then(([component]) => {
      // console.log("current here", storeReducer);
			injectAsyncReducer(storeReducer);
			return component.default;
		})
		.catch(err => {
			throw err;
		});
	return state;
}

/**
 * 页面加载配置
 */
export default function PageLoader(options: any = {}) {
	const opt: any = {
		onEnter: options.onEnter || undefined,
		loading: options.loading || noop,
		loader: options.loader || noop,
		error: options.error || noop,
		reducer: options.reducer || {}
	};

	let stateStore: any = null;

	if (options.onEnter && typeof options.onEnter !== 'function') {
		throw new Error('Config onEnter must be function');
	}

	return class PLoader extends React.PureComponent<any, any> {
		constructor(props) {
			super(props);
			stateStore = perLoad(opt.loader, opt.reducer);
			this.state = {
				PageComponent: stateStore.Component,
				isLoading: true,
				hasError: false,
				error: false,
				errorInfo: null
			};
		}

		async componentDidMount() {
			try {
				const pageComponent = await stateStore.promise;
				if (opt.onEnter) {
					await opt.onEnter(this.props);
        }
        // console.log("pageComponent: ", pageComponent);
				this.setState({
					PageComponent: pageComponent
				});
			} catch (err) {
        console.error("has some thing error: ", err);
				this.setState({
					error: true,
					errorInfo: JSON.stringify(err.message || '哦，出错了！')
				});
			} finally {
				this.setState({
					isLoading: false
				});
			}
		}

		componentWillUnmount() {
			// remove dynamic reducer
			if (opt.reducer) {
				const storeNames = Object.keys(opt.reducer);
				injectAsyncReducer(
					storeNames.reduce((o, key) => {
						o[key] = false;
						return o;
					}, {})
				);
			}
		}

		render() {
			const { isLoading, PageComponent, error, errorInfo } = this.state;
			if (isLoading) {
				return <opt.loading />;
			}

			if (error) {
				return <opt.error errmsg={`Oops！出错了！${errorInfo}`} />;
			}
			return <PageComponent {...this.props} />;
		}
	};
}
